-
Notifications
You must be signed in to change notification settings - Fork 1.1k
fix: arithmetic overflow in mDNS TTL implementation #5967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two nits, rest LGTM. Thanks!
.filter(move |peer| peer.id() != &local_peer_id) | ||
.filter(move |peer| now.checked_add(peer.ttl()).is_some()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.filter(move |peer| peer.id() != &local_peer_id) | |
.filter(move |peer| now.checked_add(peer.ttl()).is_some()) | |
.filter(move |peer| peer.id() != &local_peer_id && peer.ttl() > now) |
No need for multiple Filter
wrappers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, just saw that my above suggestion doesn't make any sense. I meant:
.filter(move |peer| peer.id() != &local_peer_id) | |
.filter(move |peer| now.checked_add(peer.ttl()).is_some()) | |
.filter(move |peer| peer.id() != &local_peer_id && now.checked_add(peer.ttl()).is_some()) |
Still, I am not a big fan of calculation the now + peer.ttl()
sum twice. Why not use ffilter_map
and return the now.checked_add(peer.ttl())
Option
so it can be used directly in the next step?
Hey hey, thank you for your responses. // Use a reasonable maximum - 1 day should be sufficient for most scenarios
const MAX_TTL: Duration = Duration::from_secs(60 * 60 * 24);
pub(crate) fn extract_discovered(
&self,
now: Instant,
local_peer_id: PeerId,
) -> impl Iterator<Item = (PeerId, Multiaddr, Instant)> + '_ {
self.discovered_peers()
.filter(move |peer| peer.id() != &local_peer_id)
// Remove this filter to keep all peers
// .filter(move |peer| now.checked_add(peer.ttl()).is_some())
.flat_map(move |peer| {
let observed = self.observed_address();
// Cap expiration time to avoid overflow
let new_expiration = match now.checked_add(peer.ttl()) {
Some(expiration) => expiration,
None => {
now.checked_add(MAX_TTL)
.unwrap_or(now) // Fallback to now if even that overflows (extremely unlikely)
}
};
peer.addresses().iter().filter_map(move |address| {
let new_addr = _address_translation(address, &observed)?;
let new_addr = new_addr.with_p2p(*peer.id()).ok()?;
Some((*peer.id(), new_addr, new_expiration))
})
})
} |
On the other hand, we're still not solving the essence of this problem. |
Can you expand on that? Why would a non-malicious peer set a TTL that is large enough to cause an overflow?
What issue? |
My initial reaction is that the mDNS protocol itself shouldn't be responsible for handling security. If we're implementing changes that address security concerns, we should consider handling them at a higher layer, outside the mDNS protocol itself. Completely failing the response would be overly harsh - we'd lose all the valid data in the response because of one overly enthusiastic TTL.
I think that we can't be sure whether the problematic TTLs are caused by malicious actors or if the responses were simply malformed. It seems important to investigate the creation of Finally, I would argue that it might be best to address this at the decoding stage rather than later in the process. This way, we can catch any malformed data earlier on and handle it more gracefully. |
If we packet is malformed we should discard the whole packet anyway. I don't think there is a way to recover from it. How are we supposed to know what other fields are correct? |
This is turning into more of a design decision than we expected.
We’re still not entirely sure why TTL values are coming in this way, and it feels a bit “nuclear” to filter everything out, because it seems that there is some hidden problem somewhere. |
We are using
We could add a debug message when discarding a packet and print the discarded package, wouldn't that solve this problem? |
Exactly, and this package is still in its alpha stage. That's why I was thinking about the ease of debugging.
Your call on this one — I’m happy to jump in and help whichever way you go! That said, your proposed solution works for me too — I just don’t have the same inside scoop on how you all usually like to handle these things. |
Description
This PR tries to fix possible arithmetic overflows in the mDNS implementation when processing response packets with tremendous TTL values.
Fixes #5943
Notes & open questions
I’ve kept the source in its original form and added a new filter combinator. This feels like a small, minimal change and, in my opinion, the cleanest solution.
Change checklist